package game.Rendering;

import game.*;
import game.Audio.AudioResources;
import game.Gamemode.*;
import game.Map.Map;
import game.Map.MapChunk;
import game.Player.Input;
import game.Player.Player;
import game.Player.Team;
import game.Sprites.Sprite;
import game.Sprites.SpriteResources;
import game.Utils.AnimatedDouble;
import game.Utils.GraphicsUtils;
import game.Sprites.SpriteSheet;
import game.Sprites.Transparency;
import game.Weapons.Weapon_info;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Point2D;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.BlendMode;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.Text;
import org.apache.commons.lang.StringUtils;

import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Camera extends SceneObject {
    private Vector3 position;
    private double size;
    private Scene scene;
    //private SpriteSheet hudNumbers;
    private Image marker;
    private Image bombRadarImg;
    private List<Image> hudNumbers;
    private SpriteSheet hudSymbols;
    private Image radar;
    private List<List<Weapon_info>> storeWeapons;

    private int currentPlayer; // Spectating player index in playerlist

    private boolean storeOpen = false;
    private boolean escMenuOpen = false;

    private int renderPanel = -1;
    private int storeError = 0; //0 no error, -1 not enough money

    private String[] classes = {"Handgun", "Shotgun", "Sub Machine Gun", "Rifle", "Machine Gun", "Equipment"};
    private List<Rectangle2D> buttons;
    LinearGradient buttonGradient;
    private int storeWidth = 600; //storeWidth = 600 = 15cm
    private int storeHeight = 440; //storeHeight = 440 = 11cm
    private Point storeReference;
    private int buttonWidth;
    private int buttonHeight;
    private int xOffset;
    private int yOffset;
    private int fontHeight = 13;
    private int arc = 5;
    private Font f12 = new Font("Arial", fontHeight);

    // UI HELPERS
    public AnimatedDouble moneyAnim = new AnimatedDouble(0.0, 1.0, 2.0);
    public AnimatedDouble shopOpenAnim = new AnimatedDouble(0.0, 1.0, 0.25);
    public AnimatedDouble escMenuAnim = new AnimatedDouble(0.0, 1.0, 0.25);
    public AnimatedDouble buyErrorAnim = new AnimatedDouble(1.0, 0.0, 1.0, true);
    public AnimatedDouble shopErrorAnim = new AnimatedDouble(1.0, 0.0, 1.0, true);
    protected AnimatedDouble roundWinAnim = new AnimatedDouble(1.0, 0.0, 3.0, true);
    protected String roundWinText;

    // Sounds
    protected Clip escMenuSound;

    protected List<Line2D> debugLines;
    protected List<String> centerMessages;

    /**
     * Adds a line to be drawn when debugging on the next frame.
     * Must be called on lateUPDATE.
     *
     * @param line
     */
    public void addDebugLine(Line2D line) {
        debugLines.add(line);
    }

    /**
     *
     */
    public void addCenterMessage(String message) {
        centerMessages.add(message);
    }

    public Camera(Scene scene, Vector3 position, double size) throws Exception {
        this.scene = scene;
        this.position = position;
        this.size = size;
        Helper.myCamera = this;
        this.initHud();
        buttons = new ArrayList<>();
        Color color = new Color(30 / 255.0, 30 / 255.0, 30 / 255.0, 200 / 255.0);
        Stop[] stops = new Stop[]{new Stop(0, Color.LIGHTGREY), new Stop(1, color)};
        this.buttonGradient = new LinearGradient(0, 0, 0, 0.5, true, CycleMethod.NO_CYCLE, stops);
        this.buttonWidth = 2 * storeWidth / 5;
        this.buttonWidth -= (buttonWidth / 5);
        this.buttonHeight = (storeHeight / 18);
        this.xOffset = (storeWidth / 5);
        this.yOffset = (buttonHeight / 6);
        currentPlayer = 0;

        debugLines = new ArrayList<Line2D>();
        centerMessages = new ArrayList<String>();
        escMenuSound = AudioResources.loadClip("audio/wpn_moveselect.wav");
    }

    private Vector3 globalToScreen(Vector3 pos) {
        double ratio = (double) GameCanvas.getInstance().getWidth() / (double) GameCanvas.getInstance().getHeight();
        double cameraWidth = size * ratio;
        Vector3 cameraCornerPos = new Vector3(position.x - cameraWidth / 2, position.y - size / 2, 0.0);
        return pos.sub(cameraCornerPos).multiply((double) GameCanvas.getInstance().getHeight() / size);
    }

    protected boolean boundsAreVisible(Rectangle2D bounds, double visionAngle, double tacticVisionFov) {
        boolean visible = false;
        Map map = this.scene.getMap();
        Point cameraTile = map.globalToTilePos(getPosition());
        Point spriteLeftCorner = map.globalToTilePos(new Vector3(bounds.getMinX(), bounds.getMinY(), 0));
        Point spriteRightCorner = map.globalToTilePos(new Vector3(bounds.getMaxX(), bounds.getMaxY(), 0));
        for (int x = spriteLeftCorner.x; x <= spriteRightCorner.x && !visible; x++) {
            for (int y = spriteLeftCorner.y; y <= spriteRightCorner.y && !visible; y++) {
                if (map.is_viewed_from(cameraTile, new Point(x, y), visionAngle, tacticVisionFov)) {
                    visible = true;
                    break;
                }
            }
        }
        return visible;
    }

    public void draw(GraphicsContext gd) {

        int screenWidth = (int) GameCanvas.getInstance().getWidth();
        int screenHeight = (int) GameCanvas.getInstance().getHeight();

        if (this.scene != null && this.scene.getMap() != null) {
            gd.setFill(this.scene.getMap().getBackgroundColor());
            gd.fillRect(0, 0, screenWidth, screenHeight);
        }

        double ratio = (double) screenWidth / screenHeight;
        double squareRes = (double) screenHeight / size; // in pixels/meter
        double cameraWidth = size * ratio; // meters

        Rectangle2D.Double cameraRectangle = new Rectangle2D.Double(position.x - cameraWidth / 2, position.y - size / 2, size * ratio, size);
        Vector3 leftCameraCornerPos = new Vector3(cameraRectangle.x, cameraRectangle.y, 0);
        Vector3 rightCameraCornerPos = new Vector3(cameraRectangle.x + cameraRectangle.width, cameraRectangle.y + cameraRectangle.height, 0);


        // Draw map tiles (chunks) on camera
        Map map = this.scene.getMap();
        double fixGaps = 0.02;
        List<MapChunk> chunksVisible = map.getChunksInArea(leftCameraCornerPos, rightCameraCornerPos);
        gd.setFill(map.getBackgroundColor());
        for (int i = 0; i < chunksVisible.size(); i++) {
            MapChunk chunk = chunksVisible.get(i);
            Vector3 chunkLeftCornerGlobalPos = chunk.getPosition().sub(new Vector3(fixGaps, fixGaps, 0.0));
            Vector3 chunkRightCornerGlobalPos = chunkLeftCornerGlobalPos.add(
                    new Vector3(map.getTileSize() * chunk.getSize(), map.getTileSize() * chunk.getSize(), 0.0))
                    .add(new Vector3(fixGaps, fixGaps, 0.0));


            Vector3 leftCornerScreenPos = globalToScreen(chunkLeftCornerGlobalPos);
            Vector3 rightCornerScreenPos = globalToScreen(chunkRightCornerGlobalPos);


            int width = (int) (rightCornerScreenPos.x - leftCornerScreenPos.x + 0.5);
            int height = (int) (rightCornerScreenPos.y - leftCornerScreenPos.y + 0.5);

            javafx.scene.image.Image img = chunk.getChunkImage();
            if (img != null) {
                gd.drawImage(img, leftCornerScreenPos.x, leftCornerScreenPos.y, width, height);
            }
        }

        // Draw tactic vision overlay
        Point cameraTile = map.globalToTilePos(getPosition());
        double tacticVisionFov = Math.toRadians(120);

        // Get following player rotation
        double visionAngle = 0;
        if (Player.myPlayer != null && Player.myPlayer.isAlive()) {
            visionAngle = Player.myPlayer.getRotation();
        } else if (currentPlayer >= 0 && currentPlayer < GamemodeManager.getInstance().getPlayerList().size()) {
            Player pl = GamemodeManager.getInstance().getPlayerList().get(currentPlayer);
            if (pl != null && pl.isAlive()) {
                visionAngle = pl.getRotation();
            }
        }

        // Draw tactic overlay
        if (Configuration.getTacticVision()) {
            Point leftCornerTile = map.globalToTilePos(leftCameraCornerPos);
            Point rightCornerTile = map.globalToTilePos(rightCameraCornerPos);
            gd.setFill(Color.rgb(0, 0, 0, 0.6));
            for (int x = leftCornerTile.x; x <= rightCornerTile.x; x++) {
                for (int y = leftCornerTile.y; y <= rightCornerTile.y; y++) {
                    // Get tile position in screen
                    Point tilePos = new Point(x, y);
                    Vector3 tileLeftCorner = globalToScreen(map.tileToGlobalPos(tilePos));
                    Vector3 tileRightCorner = globalToScreen(map.tileToGlobalPos(new Point(x + 1, y + 1)));
                    double width = tileRightCorner.x - tileLeftCorner.x;
                    double height = tileRightCorner.y - tileLeftCorner.y;

                    if (map.is_viewed_from(cameraTile, tilePos, visionAngle, tacticVisionFov)) {

                    } else {
                        gd.fillRect(tileLeftCorner.x, tileLeftCorner.y, width + 0.2, height + 0.2);
                    }
                }
            }

        }

        // Comprobar sprites que ve la camara en pantalla
        List<Sprite> sprites = scene.getSprites();
        List<Sprite> visibleSprites = new ArrayList<Sprite>();
        for (int i = 0; i < sprites.size(); i++) {
            Sprite sprite = sprites.get(i);
            if (sprite == null) {
                continue;
            }
            // Clipping (Render only sprites inside camera space)
            Rectangle2D bounds = sprite.getBound();
            if (bounds == null) {
                continue;
            }

            if (cameraRectangle.intersects(bounds)) {
                // Agregar a visible para pintar despues
                if (!Configuration.getTacticVision())
                    visibleSprites.add(sprite);
                else {
                    // Comprobar si está en área visible
                    boolean visible = boundsAreVisible(bounds, visionAngle, tacticVisionFov);
                    if (visible)
                        visibleSprites.add(sprite);
                }
            }
        }
        // Ordenar sprites que ve la camara por profundidad (mas lejanos primero)
        Collections.sort(visibleSprites, new Sprite.SortByDepth());

        gd.save();
        //TODO: Draw marker and add Configuration condition
        if (Player.myPlayer != null && Player.myPlayer.isAlive()) {
            //gd.setFill(Color.RED);
            Color markerColor = Player.myPlayer.getTeam().getTeamColor();
            double markerSize = 1.4;
            gd.setGlobalBlendMode(BlendMode.SCREEN);
            ColorAdjust colorAdjust = new ColorAdjust();
            double hue = map((markerColor.getHue() + 180) % 360, 0, 360, -1, 1);
            colorAdjust.setHue(hue);
            colorAdjust.setBrightness(0.0);
            colorAdjust.setSaturation(markerColor.getSaturation());
            gd.setEffect(colorAdjust);
            int markerWidth = (int) (this.marker.getWidth());
            int markerHeight = (int) (this.marker.getHeight());
            gd.drawImage(this.marker, (screenWidth - markerSize * squareRes) / 2.0, (screenHeight - markerSize * squareRes) / 2.0,
                    squareRes * markerSize, squareRes * markerSize);
        }
        gd.restore();

        // Dibujar sprites que ve la camara en pantalla
        for (int i = 0; i < visibleSprites.size(); i++) {
            Sprite sprite = visibleSprites.get(i);
            if (sprite == null)
                continue;

            Vector3 screenPos = globalToScreen(sprite.getPosition());
            sprite.draw(gd, screenPos, squareRes);
        }
        gd.restore();


        // Render scene light in a different additive image and then add to g2d
        //BufferedImage additiveImage = new BufferedImage(screenWidth, screenHeight, BufferedImage.TYPE_4BYTE_ABGR);
        // Graphics2D additiveg2d = additiveImage.createGraphics();

        // Enable additive mode
        gd.save();
        gd.setGlobalBlendMode(BlendMode.ADD);
        gd.setFill(Color.BLACK);
        Image flareImg = SpriteResources.getFlareImage();
        List<PointLight> lights = scene.getLights();
        for (int i = 0; i < lights.size(); i++) {
            PointLight light = lights.get(i);
            if (light == null)
                continue;

            Vector3 screenPos = globalToScreen(light.getPosition());
            double lightPixelRadius = squareRes * light.getRadius();

            Rectangle2D lightBounds = new Rectangle2D.Double(light.getPosition().x - light.getRadius(),
                    light.getPosition().y - light.getRadius(), light.getRadius() * 2, light.getRadius() * 2);
            //g2D.setColor(light.getColor());

            ColorAdjust lightAdjust = new ColorAdjust();
            Color lightColor = light.getColor();
            lightAdjust.setHue(lightColor.getHue() / 360.0);
            lightAdjust.setBrightness(0.0);
            lightAdjust.setSaturation(lightColor.getSaturation());
            gd.setEffect(lightAdjust);
            if (!Configuration.getTacticVision() || boundsAreVisible(lightBounds, visionAngle, tacticVisionFov)) {
                gd.drawImage(flareImg, (int) (screenPos.x - lightPixelRadius), (int) (screenPos.y - lightPixelRadius),
                        (int) (lightPixelRadius * 2), (int) (lightPixelRadius * 2));
            }
        }
        gd.restore();


        //g2D.setColor(Color.red);
        //g2D.fillRect(5, 5, 200, 50);
        if (Player.myPlayer != null && Player.myPlayer.isAlive() && !GamemodeManager.getInstance().isGameFinished()) {
            drawHud(gd, leftCameraCornerPos, rightCameraCornerPos, squareRes, cameraWidth, ratio);

        } else if (!GamemodeManager.getInstance().isGameFinished()) {
            // Spectate
            drawSpectatingMenu(gd);
        }

        if (!GamemodeManager.getInstance().isGameFinished()) {
            gd.setEffect(new DropShadow(5, 1, 1, Color.BLACK));
            gd.setTextAlign(TextAlignment.CENTER);
            if (roundWinAnim.getValue() > 0.0) {
                double opacity = Math.min(roundWinAnim.getValue() * 2, 1.0);

                gd.setFill(Color.rgb(255, 255, 0, opacity));
                gd.fillText(roundWinText, screenWidth / 2, screenHeight / 4);
            }
            gd.setEffect(null);
            gd.setTextAlign(TextAlignment.LEFT);
        }

        if (Configuration.isChatCommunication())
            drawChat(gd);

        drawKills(gd);

        // Draw center messages
        if (Player.myPlayer != null && Player.myPlayer.isAlive() && Player.myPlayer.hasBomb() && Player.myPlayer.isInBombZone()) {
            addCenterMessage("Press P to plant the bomb");
        }
        if (Player.myPlayer != null && Player.myPlayer.isAlive() && GamemodeManager.getInstance() instanceof StandardManager &&
                Player.myPlayer.getTeam() == ((StandardManager) GamemodeManager.getInstance()).getCounterTeam() &&
                Player.myPlayer.isInDefusingRange()) {
            addCenterMessage("Press F to defuse the bomb");
        }

        java.awt.geom.Point2D.Double msgScreenPos = new java.awt.geom.Point2D.Double(screenWidth / 2, screenHeight / 2 + squareRes * 1.5);
        gd.setFill(Color.YELLOW);
        gd.setEffect(new DropShadow(5, 0, 2, Color.BLACK));
        gd.setTextAlign(TextAlignment.CENTER);
        for (String msg : centerMessages) {
            gd.fillText(msg, msgScreenPos.getX(), msgScreenPos.getY());
            break;//ONly print first message
        }
        gd.setEffect(null);
        gd.setFill(Color.BLACK);
        gd.setTextAlign(TextAlignment.LEFT);


        if (storeOpen) {
            drawStore(gd);
        }

        // Draw tab when pressing tab, dead or dont have a player
        if (Input.getKey(KeyCode.valueOf("TAB")) || GamemodeManager.getInstance().isGameFinished() ||
                Player.myPlayer == null) {
            drawTabMenu(gd);
            setStoreOpen(false);
        }

        if (GamemodeManager.getInstance().isGameFinished()) {
            gd.setFont(new javafx.scene.text.Font("Arial", (int) (48 * getHudScale())));
            double textHeight = new Text("Test").getLayoutBounds().getHeight();
            gd.setTextAlign(TextAlignment.CENTER);
            gd.setEffect(new DropShadow(0, 0, 5, Color.BLACK));
            gd.setFill(GamemodeManager.getInstance().getGameFinishedColor());
            gd.fillText(GamemodeManager.getInstance().getGameFinishedText(), screenWidth / 2, 48 * getHudScale() + textHeight);

            gd.setFill(Color.WHITE);
            gd.setFont(new javafx.scene.text.Font("Arial", (int) (28 * getHudScale())));
            gd.fillText("Press SPACE to continue...", screenWidth / 2, screenHeight - 32 * getHudScale());
            gd.setTextAlign(TextAlignment.LEFT);
            gd.setEffect(null);
        }

        if (escMenuOpen) {
            drawEscMenu(gd);
        }

        // Draw debugging lines
        if(false){
            for (Line2D line : debugLines) {
                Vector3 point1 = new Vector3(line.getX1(), line.getY1(), 0.0);
                Vector3 point2 = new Vector3(line.getX2(), line.getY2(), 0.0);

                Vector3 screen1 = globalToScreen(point1);
                Vector3 screen2 = globalToScreen(point2);

                gd.setStroke(Color.GREEN);
                gd.strokeLine(screen1.x, screen1.y, screen2.x, screen2.y);
            }

        }
    }


    /**
     * Plays a sound clip in a 3d position in the world.
     *
     * @param clip     Audio clip.
     * @param soundPos Position of the sound in the world.
     */
    public void play3DSound(Clip clip, Vector3 soundPos) {
        if (clip == null) {
            return;
        }

        // Check 3d distance for volume
        double maxDist = 25.0;
        double dist = Vector3.distance2d(soundPos, this.getPosition());
        if (dist > maxDist) {
            return;
        }


        // Set volumen value
        FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
        Double volume = Double.valueOf(Configuration.getInstance().getVolumeGame()) * Double.valueOf(Configuration.getInstance().getVolumeMaster()) / 10000;
        double gain = 1.0 - (dist / maxDist);   // gain entre 0 y 1

        if (gain * volume < 0.01) {
            return;
        }

        float dB = (float) (Math.log(gain * volume) / Math.log(10.0) * 20.0);
        dB = Math.max(dB, -70.0f);
        gainControl.setValue(dB);

        // Play clip
        if (clip.isRunning() || clip.isActive()) {
            clip.stop();
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        clip.setMicrosecondPosition(0);
        clip.start();      // Play clip
    }

    public Vector3 getPosition() {
        return this.position;
    }

    public double getSize() {
        return this.size;
    }

    public void update(double deltaTime) {
        debugLines.clear();
        centerMessages.clear();

        if (Player.myPlayer != null && Player.myPlayer.isAlive()) {
            this.position = Player.myPlayer.getPosition();
        } else if (currentPlayer >= 0 && currentPlayer < GamemodeManager.getInstance().getPlayerList().size()) {
            if (Input.getKeyClick(KeyCode.SPACE)) {
                currentPlayer = (currentPlayer + 1) % GamemodeManager.getInstance().getPlayerList().size();
            }

            Player pl = GamemodeManager.getInstance().getPlayerList().get(currentPlayer);
            int tries = 0;
            while (pl == null || !pl.isAlive() && tries < GamemodeManager.getInstance().getPlayerList().size()) {
                currentPlayer = (currentPlayer + 1) % GamemodeManager.getInstance().getPlayerList().size();
                pl = GamemodeManager.getInstance().getPlayerList().get(currentPlayer);
                tries++;
            }
        }

        if (Input.getKeyClick(KeyCode.ESCAPE)) {
            setEscMenuOpen(!isEscMenuOpen());
        }

        if (isEscMenuOpen()) {
            updateEscMenu();
        }
        if (Scene.getInstance() == null) {
            return;
        }

        if (GamemodeManager.getInstance().isGameFinished()
                && (Input.getKeyClick(KeyCode.SPACE) || Input.getKeyClick(KeyCode.ENTER))) {
            //TODOd
            System.out.println("Delete scene and camera n everything and Go back to main menu");
            Scene.getInstance().destroy();
        }
    }

    @Override
    public void lateupdate(double deltaTime) {
        if (Player.myPlayer != null && Player.myPlayer.isAlive()) {
            this.position = Player.myPlayer.getPosition();
        } else if (currentPlayer >= 0 && currentPlayer < GamemodeManager.getInstance().getPlayerList().size()) {
            Player pl = GamemodeManager.getInstance().getPlayerList().get(currentPlayer);
            if (pl != null && pl.isAlive()) {
                this.position = pl.getPosition();
            }
        }
    }

    //TODO: Resaltar jugador (altera el orden de los fondos que se pintan)
    private void drawTeam(GraphicsContext gd, Point topLeft, Color teamColor, List<Player> players, double scaleHUD, double menuWidth, double menuHeight) {
        Font f = new javafx.scene.text.Font("TimesRoman", (int) (18 * scaleHUD));
        double headerWidth = menuWidth / 2.05;
        double headerHeight = menuHeight / 18;
        double smallColumnWidth = headerWidth / 12;
        double bigColumnWidth = headerWidth / 2;
        Text auxText = new Text("Player Score Deaths");
        auxText.setFont(f);
        gd.setFill(teamColor);
        gd.setStroke(teamColor);
        double textHeight = auxText.getLayoutBounds().getHeight();
        double yPos = topLeft.y + (textHeight + menuHeight / 29) / 2.5;
        auxText.setText("Deaths");
        double gap = headerWidth / 3.0 - auxText.getLayoutBounds().getWidth();
        double xPlayerCol = topLeft.x;

        gd.setEffect(new DropShadow(2, 2, 1, Color.BLACK));
        gd.fillText("Player", xPlayerCol, yPos);
        double xScoreCol = topLeft.x + bigColumnWidth;
        gd.fillText("Score", xScoreCol, yPos);
        double xDeathsCol = topLeft.x + bigColumnWidth + smallColumnWidth + gap;
        gd.fillText("Deaths", xDeathsCol, yPos);
        gd.setEffect(null);

        Color transparentColor = new Color(teamColor.getRed() * 0.5, teamColor.getGreen() * 0.5, teamColor.getBlue() * 0.5, 40 / 255.0);
        double height = 3 * headerHeight / 4.0;
        yPos += textHeight / 2.5;
        gd.setStroke(teamColor);
        gd.strokeLine(xPlayerCol, yPos, xPlayerCol + headerWidth, yPos);
        boolean paint = true;
        players.sort(Comparator.comparing(Player::getKillCount).reversed());
        for (Player p : players) {
            Color plBackgroundColor = transparentColor;
            if (p == Player.myPlayer) {
                plBackgroundColor = teamColor.brighter();
                plBackgroundColor = new Color(teamColor.getRed(), teamColor.getGreen(), teamColor.getBlue(), 60 / 255.0);
            }

            if (paint || p == Player.myPlayer) {
                gd.setFill(plBackgroundColor);
                gd.fillRoundRect(xPlayerCol, yPos, headerWidth, height, 0, 0);
            }
            Color plColor = teamColor;
            if (!p.isAlive())
                plColor = Color.GRAY;

            gd.setFill(plColor);
            gd.setEffect(new DropShadow(2, 2, 1, Color.BLACK));
            paint = !paint;
            gd.fillText(p.getName(), xPlayerCol, yPos + (height + textHeight) / 2.5);
            gd.fillText(String.valueOf(p.getKillCount()), xScoreCol, yPos + (height + textHeight) / 2.5);
            gd.fillText(String.valueOf(p.getDeathCount()), xDeathsCol, yPos + (height + textHeight) / 2.5);
            gd.setEffect(null);
            yPos += height;
        }
    }

    public void drawSpectatingMenu(GraphicsContext gc) {
        gc.save();
        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();
        double scaleHUD = getHudScale();
        double vSpace = 128 * scaleHUD;
        double hSpace = (512 + 48) * scaleHUD;
        double symbolSize = 32 * scaleHUD;
        gc.setGlobalBlendMode(BlendMode.SRC_OVER);
        gc.setFill(Color.BLACK);
        gc.fillRect(0, 0, screenWidth, vSpace);
        gc.setFont(new javafx.scene.text.Font("Arial", (int) (28 * scaleHUD)));

        // TOP
        Text auxText = new Text("You are dead");
        auxText.setFont(gc.getFont());
        double textHeight = auxText.getLayoutBounds().getHeight();

        gc.setTextAlign(TextAlignment.CENTER);
        gc.setFill(Color.RED);
        gc.fillText("You are dead!", screenWidth / 2, vSpace / 4 + textHeight / 2);
        gc.setFill(Color.WHITE);
        gc.fillText("Spectating", screenWidth / 2, vSpace / 4 * 3 + textHeight / 2);

        //Draw time
        double dTime = (int) GamemodeManager.getInstance().getRemainingTime();
        int minutes = (int) dTime / 60;
        String minutesString = minutes+"";
        if(minutes < 10){
            minutesString = "0"+minutesString;
        }
        int seconds = (int) dTime % 60;
        String secondsString = seconds+"";
        if(seconds < 10){
            secondsString = "0"+secondsString;
        }
        gc.setTextAlign(TextAlignment.RIGHT);


        Image timeImg = hudSymbols.get(2);
        if (GamemodeManager.getInstance() instanceof StandardManager && ((StandardManager) GamemodeManager.getInstance()).isBombPlanted()) {
            timeImg = hudSymbols.get(6);
        }
        auxText = new Text(minutesString + ":" + secondsString);
        auxText.setFont(gc.getFont());
        double textWidth = auxText.getLayoutBounds().getWidth();
        textHeight = auxText.getLayoutBounds().getHeight();
        gc.drawImage(timeImg,
                screenWidth - 48*scaleHUD - textWidth - symbolSize,
                vSpace / 4 + textHeight / 4*3 - symbolSize,
                symbolSize, symbolSize);

        gc.fillText(minutesString + ":" + secondsString, screenWidth - 32*scaleHUD, vSpace / 4 + textHeight / 2);

        // Draw money
        if(Player.myPlayer != null) {
            gc.fillText(Player.myPlayer.getMoney()+"", screenWidth - 32 * scaleHUD, vSpace / 4 * 3 + textHeight / 2);

            auxText = new Text(Player.myPlayer.getMoney()+"");
            auxText.setFont(gc.getFont());
            textWidth = auxText.getLayoutBounds().getWidth();

            Image moneyImg = hudSymbols.get(7);
            gc.drawImage(moneyImg,
                    screenWidth - 48*scaleHUD - textWidth - symbolSize,
                    vSpace / 4 * 3 + textHeight / 4*3 - symbolSize,
                    symbolSize, symbolSize);
        }


        // BOTTOM
        gc.setTextAlign(TextAlignment.CENTER);
        gc.setFill(Color.BLACK);
        gc.fillRect(0, screenHeight - vSpace, screenWidth, vSpace);
        gc.setFill(Color.RED);
        if (currentPlayer >= 0 && currentPlayer < GamemodeManager.getInstance().getPlayerList().size()) {
            Player pl = GamemodeManager.getInstance().getPlayerList().get(currentPlayer);
            if (pl != null && pl.isAlive()) {
                gc.setFill(pl.getTeam().getTeamColor());
                gc.fillText(pl.getName(), screenWidth / 2, screenHeight - vSpace / 2 + textHeight / 2);
            }
        }
        gc.setTextAlign(TextAlignment.LEFT);
        gc.setFill(Color.WHITE);
        gc.fillText("Press SPACE to switch player.", 32*scaleHUD, screenHeight - vSpace / 2 + textHeight / 2);

        gc.setTextAlign(TextAlignment.RIGHT);
        gc.setFill(Color.WHITE);
        gc.fillText("Hold TAB to open the scoreboard.", screenWidth - 32*scaleHUD, screenHeight - vSpace / 2 + textHeight / 2);

        gc.restore();
    }

    public void showRoundWinMessage(String msg){
        roundWinAnim.reset();
        roundWinText = msg;
    }
    //TODO: Ajustar para distintos modos de juego
    private void drawTabMenu(GraphicsContext gd) {
        gd.save();
        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();
        double scaleHUD = getHudScale();

        double vSpace = 256 * scaleHUD;
        double hSpace = (512 + 48) * scaleHUD;
        double menuWidth = screenWidth - hSpace;
        double menuHeight = screenHeight - vSpace;

        Point topLeft = new Point((int) (screenWidth / 2 - menuWidth / 2), (int) (screenHeight / 2 - menuHeight / 2));
        // Menu Background
        gd.setFill(Color.rgb(0, 0, 0, 0.7));
        gd.fillRect(topLeft.x, topLeft.y, menuWidth, menuHeight);

        //g2D.setColor(Color.green);
        Font f = new javafx.scene.text.Font("TimesRoman", (int) (22 * scaleHUD));
        gd.setFont(f);
        gd.setFill(Color.YELLOW);
        //TODO: Mostrar FPS
        Text auxText = new Text("CS2D");
        auxText.setFont(f);
        double headerWidth = menuWidth / 2.05;
        double headerHeight = menuHeight / 18;
        double lateralMarginOffset = (menuWidth - 2 * headerWidth) / 5.0;
        Point auxPoint = new Point(topLeft.x, topLeft.y);
        gd.fillText("CS2D", topLeft.x + 2 * lateralMarginOffset, topLeft.y + auxText.getLayoutBounds().getHeight());
        gd.setFill(Color.LIGHTGREEN);
        auxText.setText(Helper.mainScene.getMap().getName());
        auxPoint.y += auxText.getLayoutBounds().getHeight();
        gd.fillText(Helper.mainScene.getMap().getName(), topLeft.x + menuWidth - 2 * lateralMarginOffset - auxText.getLayoutBounds().getWidth(), auxPoint.y);

        auxPoint.y += menuHeight / 48;

        GamemodeManager mode = GamemodeManager.getInstance();
        if (mode instanceof TeamDeathmatchManager || mode instanceof StandardManager) {
            Team ctTeam, tTeam;
            if (mode instanceof TeamDeathmatchManager) {
                ctTeam = ((TeamDeathmatchManager) mode).getCounterTeam();
                tTeam = ((TeamDeathmatchManager) mode).getTerroristTeam();
            } else {
                ctTeam = ((StandardManager) mode).getCounterTeam();
                tTeam = ((StandardManager) mode).getTerroristTeam();
            }
            int nPlayers = ctTeam.getPlayers().size();
            //TODO: Formatear bien este texto al pintarlo
            String text = "Counter-Terrorist Forces " + nPlayers + " Player";
            if (nPlayers > 1) text += "s";
            //Draw headers
            gd.setEffect(new DropShadow(2, 2, 1, Color.BLACK));
            Color transparentBlueTeamColor = new Color(0 / 255.0, 0 / 255.0, 255 / 255.0, 150 / 255.0);
            gd.setFill(transparentBlueTeamColor);
            gd.fillRoundRect(auxPoint.x + 2 * lateralMarginOffset, auxPoint.y, headerWidth, headerHeight, 0, 0);
            auxText.setText(text);
            gd.setFill(Color.WHITE);
            gd.fillText(text, auxPoint.x + 2 * lateralMarginOffset + headerWidth / 125.0, auxPoint.y + (auxText.getLayoutBounds().getHeight() + headerHeight) / 2.5);
            if (mode instanceof TeamDeathmatchManager)
                text = String.valueOf(((TeamDeathmatchManager) mode).getCounterWins());
            else text = String.valueOf(((StandardManager) mode).getCounterWins());


            auxText.setText(text);
            gd.fillText(text, auxPoint.x + 2 * lateralMarginOffset + headerWidth - headerWidth / 125.0 - auxText.getLayoutBounds().getWidth(), auxPoint.y + (auxText.getLayoutBounds().getHeight() + headerHeight) / 2.5);


            nPlayers = tTeam.getPlayers().size();
            //TODO: Formatear bien este texto al pintarlo
            text = "Terrorist Forces " + nPlayers + " Player";
            if (nPlayers > 1) text += "s";
            Color transparentRedTeamColor = new Color(255 / 255.0, 0 / 255.0, 0 / 255.0, 150 / 255.0);
            gd.setFill(transparentRedTeamColor);
            gd.fillRoundRect(auxPoint.x + headerWidth + 3 * lateralMarginOffset, auxPoint.y, headerWidth, headerHeight, 0, 0);
            auxText.setText(text);
            gd.setFill(Color.WHITE);
            gd.fillText(text, auxPoint.x + headerWidth + 3 * lateralMarginOffset + headerWidth / 125.0, auxPoint.y + (auxText.getLayoutBounds().getHeight() + headerHeight) / 2.5);
            if (mode instanceof TeamDeathmatchManager)
                text = String.valueOf(((TeamDeathmatchManager) mode).getTerroristWins());
            else text = String.valueOf(((StandardManager) mode).getTerroristWins());
            auxText.setText(text);
            gd.fillText(text, auxPoint.x + headerWidth + 3 * lateralMarginOffset + headerWidth - headerWidth / 125.0 - auxText.getLayoutBounds().getWidth(), auxPoint.y + (auxText.getLayoutBounds().getHeight() + headerHeight) / 2.5);
            gd.setEffect(null);

            // Draw left team
            auxPoint.x += 2 * lateralMarginOffset;
            auxPoint.y += headerHeight;
            drawTeam(gd, auxPoint, Color.BLUE, ctTeam.getPlayers(), scaleHUD, menuWidth, menuHeight);
            auxPoint.x += headerWidth + lateralMarginOffset;
            drawTeam(gd, auxPoint, Color.RED, tTeam.getPlayers(), scaleHUD, menuWidth, menuHeight);
        }
        gd.restore();
    }

    protected double getHudScale() {
        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();

        double scaleHUD = 0.5;
        if (screenHeight > 720) {
            scaleHUD = 0.75;
        }
        return scaleHUD;
    }

    private void drawHud(GraphicsContext g2D, Vector3 left, Vector3 right, double squareRes, double cameraWidth, double ratio) {
        g2D.save();
        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();

        // HUD COLORS
        //TODO Change setColor with bmps with something like tintImage() maybe better on load image
        Color orange = Color.rgb(255, 255, 0);
        Color red = Color.rgb(255, 0, 0);
        Color green = Color.rgb(0, 255, 0);

        //Instantiating the ColorAdjust class
        ColorAdjust colorAdjust = new ColorAdjust();
        colorAdjust.setContrast(1.0);
        colorAdjust.setBrightness(0.4);
        colorAdjust.setSaturation(1.0);

        Image img = hudSymbols.get(0);
        Image bImg;

        double scaleHUD = getHudScale();

        // TO DRAW DIGITS
        Image zeroImg = hudNumbers.get(0);
        int digitWidth = (int) (zeroImg.getWidth() * scaleHUD);
        int digitHeight = (int) (zeroImg.getHeight() * scaleHUD);
        int screenBorder = (int) (16 * scaleHUD);
        int symbolOffset = (int) (8 * scaleHUD); // espacio entre simbolo y digitos
        int digitOffset = (int) (2 * scaleHUD); // epsacio entre digitos

        // Draw radar
        colorAdjust.setHue(0.55);
        g2D.setFill(Color.BLACK);
        g2D.setEffect(colorAdjust);
        g2D.setGlobalBlendMode(BlendMode.SRC_OVER);
        int radarSize = (int) (256 * scaleHUD);
        double radarRatio = 15.0; //Meters
        g2D.drawImage(radar, screenBorder, screenBorder, radarSize, radarSize);

        // Draw points in radar
        double radarDotSize = 12 * scaleHUD;
        double bombRadarSize = 48*scaleHUD;
        List<Player> mates = Player.myPlayer.getTeam().getPlayers();
        List<Player> viewableEnemies = Player.myPlayer.viewableEnemies();

        List<Vector3> pointPositions = new ArrayList<>();
        List<Color> pointColor = new ArrayList<>();

        // Teammates
        for (int i = 0; i < mates.size(); i++) {
            Player pl = mates.get(i);
            if (!pl.isAlive())
                continue;

            pointPositions.add(pl.getPosition());
            if (pl == Player.myPlayer)
                pointColor.add(Color.LIGHTGREEN);
            else
                if(pl.hasBomb())
                    pointColor.add(Color.ORANGE);
                else
                    pointColor.add(Color.WHITE);
        }

        //Enemies
        for (int i = 0; i < viewableEnemies.size(); i++) {
            Player pl = viewableEnemies.get(i);
            if (!pl.isAlive())
                continue;

            pointPositions.add(pl.getPosition());
            pointColor.add(Color.RED);
        }

        // Draw dots
        g2D.setGlobalBlendMode(BlendMode.SCREEN);
        g2D.setEffect(null);
        Point2D radarCenter = new Point2D(screenBorder + radarSize / 2, screenBorder + radarSize / 2);
        for (int i = 0; i < pointPositions.size(); i++) {
            Vector3 pos = pointPositions.get(i);
            pos.z = (Player.myPlayer.getPosition().z);

            Color color = pointColor.get(i);

            // Get player dir with maximum radar size as top
            Vector3 dir = pos.sub(Player.myPlayer.getPosition());
            double dirMod = dir.mod();
            if (dirMod > radarRatio) {
                dir = dir.multiply(radarRatio / dirMod);
            }

            // Draw dot in radar (pixel dimensions)
            Point2D dir2 = new Point2D(dir.x, dir.y).multiply(radarSize / 2 / radarRatio);
            g2D.setFill(color);
            g2D.fillOval(radarCenter.getX() + dir2.getX() - radarDotSize / 2,
                    radarCenter.getY() + dir2.getY() - radarDotSize / 2,
                    radarDotSize, radarDotSize);

        }


        g2D.setEffect(colorAdjust);

        //Dropped defuse gamemode points
        if(GamemodeManager.getInstance() instanceof StandardManager){

            // DROPPED BOMB
            StandardManager mgr = (StandardManager)GamemodeManager.getInstance();
            if(mgr.isBombDropped() && mgr.getDroppedBombPosition() != null){
                Vector3 pos = mgr.getDroppedBombPosition();
                pos.z = (Player.myPlayer.getPosition().z);
                Color color = Color.ORANGE;

                // Get player dir with maximum radar size as top
                Vector3 dir = pos.sub(Player.myPlayer.getPosition());
                double dirMod = dir.mod();
                if (dirMod > radarRatio) {
                    dir = dir.multiply(radarRatio / dirMod);
                }

                // Draw sprite in radar (pixel dimensions)
                Point2D dir2 = new Point2D(dir.x, dir.y).multiply(radarSize / 2 / radarRatio);
                g2D.setFill(color);
                colorAdjust.setHue(color.getHue()/360);
                g2D.setEffect(colorAdjust);
                g2D.drawImage(bombRadarImg, radarCenter.getX() + dir2.getX() - bombRadarSize / 2,
                        radarCenter.getY() + dir2.getY() - bombRadarSize / 2,
                        bombRadarSize, bombRadarSize);

            }

            // PLANTED BOMB
            if(mgr.isBombPlanted() && mgr.getBombPosition() != null){
                Vector3 pos = mgr.getBombPosition();
                pos.z = (Player.myPlayer.getPosition().z);
                Color color = Color.RED;

                // Get player dir with maximum radar size as top
                Vector3 dir = pos.sub(Player.myPlayer.getPosition());
                double dirMod = dir.mod();
                if (dirMod > radarRatio) {
                    dir = dir.multiply(radarRatio / dirMod);
                }

                // Draw sprite in radar (pixel dimensions)
                Point2D dir2 = new Point2D(dir.x, dir.y).multiply(radarSize / 2 / radarRatio);
                g2D.setFill(color);
                colorAdjust.setHue(color.getHue()/360);
                g2D.setEffect(colorAdjust);
                g2D.drawImage(bombRadarImg, radarCenter.getX() + dir2.getX() - bombRadarSize / 2,
                        radarCenter.getY() + dir2.getY() - bombRadarSize / 2,
                        bombRadarSize, bombRadarSize);

            }

            //BOMB POINTS
            g2D.setEffect(null);
            if(Scene.getInstance().getMap().getBombPoints().size() > 0){
                char pointChar = 'A';
                for(Map.BombPoint point : Scene.getInstance().getMap().getBombPoints()){
                    Vector3 pos = point.getCenter();
                    pos.z = (Player.myPlayer.getPosition().z);
                    Color color = Color.RED;

                    // Get player dir with maximum radar size as top
                    Vector3 dir = pos.sub(Player.myPlayer.getPosition());
                    double dirMod = dir.mod();
                    if (dirMod > radarRatio) {
                        dir = dir.multiply(radarRatio / dirMod);
                    }

                    // Draw sprite in radar (pixel dimensions)
                    Point2D dir2 = new Point2D(dir.x, dir.y).multiply(radarSize / 2 / radarRatio);
                    g2D.setFill(color);
                    g2D.setTextAlign(TextAlignment.CENTER);
                    g2D.fillText(String.valueOf(pointChar).toUpperCase(), radarCenter.getX() + dir2.getX(),
                            radarCenter.getY() + dir2.getY() + g2D.getFont().getSize()/2);

                    pointChar++;
                }
            }
            g2D.setTextAlign(TextAlignment.LEFT);

        }
        colorAdjust.setHue(0);
        g2D.setEffect(null);



        // Draw planting/defusing progress
        int reloadBarWidth = (int) (256 * scaleHUD);
        int reloadBarHeight = (int) (32 * scaleHUD);
        if (Player.myPlayer.isPlanting() || Player.myPlayer.isDefusing()) {
            Point screenPos = new Point(screenWidth / 2 - reloadBarWidth / 2,
                    screenHeight / 2 + (int) squareRes + symbolOffset);

            Double progress = Player.myPlayer.plantingProgress();

            if(Player.myPlayer.isDefusing()){
                progress = Player.myPlayer.defusingProgress();
            }

            g2D.setFill(orange);
            g2D.fillRect(screenPos.x, screenPos.y, (int) (reloadBarWidth * progress), reloadBarHeight);
            g2D.setStroke(orange);
            g2D.strokeRect(screenPos.x, screenPos.y, reloadBarWidth, reloadBarHeight);
            g2D.setTextAlign(TextAlignment.CENTER);
            g2D.setFont(new javafx.scene.text.Font("TimesRoman", (int) (22 * scaleHUD)));

            if(Player.myPlayer.isDefusing()){
                g2D.fillText("Defusing...", screenPos.x + reloadBarWidth / 2, screenPos.y + reloadBarHeight * 2);
            }else{
                g2D.fillText("Planting...", screenPos.x + reloadBarWidth / 2, screenPos.y + reloadBarHeight * 2);

            }
            g2D.setTextAlign(TextAlignment.LEFT);


        }

        // Draw reloading progress
        //int reloadBarWidth = (int) (256 * scaleHUD);
        //int reloadBarHeight = (int) (32 * scaleHUD);
        if (Player.myPlayer.isReloading()) {
            Point screenPos = new Point(screenWidth / 2 - reloadBarWidth / 2,
                    screenHeight / 2 + (int) squareRes + symbolOffset);

            double progress = 1.0 - (Player.myPlayer.getTimeUntilReload() /
                    Player.myPlayer.current_weapon.getReloadTime());

            g2D.setFill(orange);
            g2D.fillRect(screenPos.x, screenPos.y, (int) (reloadBarWidth * progress), reloadBarHeight);
            g2D.setStroke(orange);
            g2D.strokeRect(screenPos.x, screenPos.y, reloadBarWidth, reloadBarHeight);
            g2D.setTextAlign(TextAlignment.CENTER);
            g2D.setFont(new javafx.scene.text.Font("TimesRoman", (int) (22 * scaleHUD)));
            g2D.fillText("Reloading...", screenPos.x + reloadBarWidth / 2, screenPos.y + reloadBarHeight * 2);
            g2D.setTextAlign(TextAlignment.LEFT);


        }

        //Draw HP
        int hp = Player.myPlayer.getHealth();
        Color healthColor = orange;
        colorAdjust.setHue(0.25);
        if (hp < 40) {
            colorAdjust.setHue(0);
            healthColor = red;
        }
        g2D.setFill(healthColor);
        g2D.setEffect(colorAdjust);

        int hpSymbolWidth = (int) (img.getWidth() * scaleHUD);
        int hpSymbolHeight = (int) (img.getHeight() * scaleHUD);
        Point screenPos = new Point(screenBorder, screenHeight - screenBorder - hpSymbolHeight);
        g2D.drawImage(img, screenPos.x, screenPos.y,
                hpSymbolWidth, hpSymbolHeight);

        // Get HP DIGITS
        List<Integer> digits;
        digits = getNDigits(hp, -1);

        // DRAW HP DIGITS
        screenPos = new Point(screenBorder + hpSymbolWidth + symbolOffset, screenHeight - screenBorder - digitHeight);

        for (int i = digits.size() - 1; i >= 0; i--) {
            bImg = hudNumbers.get(digits.get(i));
            g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
            screenPos.x += digitWidth + digitOffset;
        }

        //Draw armor
        colorAdjust.setHue(0.26);
        g2D.setEffect(colorAdjust);
        g2D.setFill(orange);
        screenPos.x += symbolOffset * 4;
        img = hudSymbols.get(1);
        g2D.drawImage(img, screenPos.x, screenPos.y, hpSymbolWidth, hpSymbolHeight);

        // Draw armor digits
        int armor = Player.myPlayer.getPlayerArmor();
        digits = getNDigits(armor, -1);
        screenPos.x += hpSymbolWidth + symbolOffset;
        for (int i = digits.size() - 1; i >= 0; i--) {
            bImg = hudNumbers.get(digits.get(i));
            g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
            screenPos.x += digitWidth + digitOffset;
        }

        //Draw time
        double dTime = (int) GamemodeManager.getInstance().getRemainingTime();
        int minutes = (int) dTime / 60;
        List<Integer> minDigits = getNDigits(minutes, -1);

        int seconds = (int) dTime % 60;
        List<Integer> secDigits = getNDigits(seconds, 2);

        int timeTotalWidth = (minDigits.size() + secDigits.size()) * digitWidth + hpSymbolWidth;
        screenPos = new Point(screenWidth / 2 - timeTotalWidth / 2, screenHeight - screenBorder - hpSymbolHeight);

        img = hudSymbols.get(2);
        if (GamemodeManager.getInstance() instanceof StandardManager && ((StandardManager) GamemodeManager.getInstance()).isBombPlanted()) {
            img = hudSymbols.get(6);
        }
        g2D.drawImage(img, screenPos.x, screenPos.y, hpSymbolWidth, hpSymbolHeight);

        // Minutes
        screenPos = new Point(screenWidth / 2 - timeTotalWidth / 2 + hpSymbolWidth + symbolOffset,
                screenHeight - screenBorder - digitHeight);
        for (int i = minDigits.size() - 1; i >= 0; i--) {
            bImg = hudNumbers.get(minDigits.get(i));
            g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
            screenPos.x += digitWidth + digitOffset;
        }

        // : symbol
        bImg = hudNumbers.get(10);
        g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
        screenPos.x += digitWidth / 3 + digitOffset;

        // Seconds
        for (int i = secDigits.size() - 1; i >= 0; i--) {
            bImg = hudNumbers.get(secDigits.get(i));
            g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
            screenPos.x += digitWidth + digitOffset;
        }
        //System.out.println("M:" + minutes + " S: " + seconds);

        //Draw ammo
        screenPos = new Point(screenWidth - screenBorder - digitWidth, screenHeight - screenBorder - digitHeight);

        //Get real ammo digits
        int totalAmmo = Player.myPlayer.getAmmoTotal();
        if (totalAmmo < 0) {
            totalAmmo = 0;
        }
        digits = getNDigits(totalAmmo, -1);

        for (int i = 0; i < digits.size(); i++) {
            bImg = hudNumbers.get(digits.get(i));
            g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
            screenPos.x -= digitWidth + digitOffset;
        }

        // Space between magazine and current ammo
        screenPos.x += digitWidth / 2;
        bImg = hudNumbers.get(11);
        g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);

        screenPos.x -= digitWidth + digitOffset;

        // Get current magazine ammo digits
        int ammo = Player.myPlayer.getAmmoCharger();
        digits = getNDigits(ammo, -1);
        //screenPos.x -= digitWidth + digitOffset; // Espacio entre magazine y real ammo
        for (int i = 0; i < digits.size(); i++) {
            bImg = hudNumbers.get(digits.get(i));
            g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
            screenPos.x -= digitWidth + digitOffset;
        }

        //Draw money
        double moneyAnimation = moneyAnim.getValue();
        colorAdjust.setHue(0.26 * moneyAnimation + 0.55 * (1.0 - moneyAnimation));
        g2D.setEffect(colorAdjust);

        screenPos = new Point(screenWidth - screenBorder - digitWidth,
                screenHeight - screenBorder - digitHeight * 2 - symbolOffset);

        // Draw money digits
        int money = Player.myPlayer.getMoney();
        digits = getNDigits(money, -1);
        for (int i = 0; i < digits.size(); i++) {
            bImg = hudNumbers.get(digits.get(i));
            g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
            screenPos.x -= digitWidth + digitOffset;
        }
        screenPos.x += digitWidth + digitOffset;

        // Draw money symbol
        screenPos.x -= symbolOffset + hpSymbolWidth;
        img = hudSymbols.get(7);
        g2D.drawImage(img, screenPos.x, screenPos.y, hpSymbolWidth, hpSymbolHeight);

        // Draw earned money animation
        if (moneyAnimation < 1.0) {
            //Green color
            colorAdjust.setHue(0.55);
            g2D.setEffect(colorAdjust);
            g2D.setGlobalAlpha(1.0 - moneyAnimation);
            screenPos = new Point(screenWidth - screenBorder - digitWidth,
                    screenHeight - screenBorder - digitHeight * 3 - symbolOffset * 2 - (int) (digitHeight * moneyAnimation));

            // Draw earned money digits
            money = Player.myPlayer.lastEarnedMoney;
            digits = getNDigits(money, -1);
            for (int i = 0; i < digits.size(); i++) {
                bImg = hudNumbers.get(digits.get(i));
                g2D.drawImage(bImg, screenPos.x, screenPos.y, digitWidth, digitHeight);
                screenPos.x -= digitWidth + digitOffset;
            }
            screenPos.x += digitWidth + digitOffset;

            // Draw earned money symbol
            screenPos.x -= symbolOffset + hpSymbolWidth;
            img = hudSymbols.get(7);
            g2D.drawImage(img, screenPos.x, screenPos.y, hpSymbolWidth, hpSymbolHeight);

            g2D.setGlobalAlpha(1.0);
        }

        //Draw buying zone
        colorAdjust.setHue(0.55);
        g2D.setEffect(colorAdjust);
        boolean inBuyingZone = Player.myPlayer.isInBuyingZone();
        Vector3 pos = new Vector3(0, 0, 0);
        if (Player.myPlayer.hasBomb && GamemodeManager.getInstance() instanceof StandardManager) {
            pos.x = (10) * ratio;
            pos.y = (int) (squareRes) * (int) (cameraWidth / 3 - 1) / ratio;
            img = hudSymbols.get(6);
            g2D.drawImage(img, (int) pos.x, (int) pos.y, (int) (img.getWidth() * scaleHUD), (int) (img.getHeight() * scaleHUD));
            //g2D.setColor(Color.green);
            g2D.setFont(new javafx.scene.text.Font("TimesRoman", (int) (22 * scaleHUD)));
            g2D.setStroke(Color.rgb(255, 255, 255));
            //TODO: Bombspot parpadeando en verde y rojo
            if (Player.myPlayer.isInBombZone())
                g2D.fillText("Bombspot", (int) pos.x + hpSymbolWidth + symbolOffset, (int) pos.y + (img.getHeight() * scaleHUD) - 22 * scaleHUD);
            else
                g2D.fillText("Bomb", (int) pos.x + hpSymbolWidth + symbolOffset, (int) pos.y + (img.getHeight() * scaleHUD) - 22 * scaleHUD);
        }
        if (Player.myPlayer.hasDefuseKit && GamemodeManager.getInstance() instanceof StandardManager) {
            pos.x = (10) * ratio;
            pos.y = (int) (squareRes) * (int) (cameraWidth / 3 - 1) / ratio;
            img = hudSymbols.get(3);
            g2D.drawImage(img, (int) pos.x, (int) pos.y, (int) (img.getWidth() * scaleHUD), (int) (img.getHeight() * scaleHUD));
            //g2D.setColor(Color.green);
            g2D.setFont(new javafx.scene.text.Font("TimesRoman", (int) (22 * scaleHUD)));
            g2D.setStroke(Color.rgb(255, 255, 255));
            if (Player.myPlayer.isInDefusingRange()) //TODO: Quitar
                g2D.fillText("Defuse the damn thing", (int) pos.x + hpSymbolWidth + symbolOffset, (int) pos.y + (img.getHeight() * scaleHUD) - 22 * scaleHUD);
            else
                g2D.fillText("Defuse Kit", (int) pos.x + hpSymbolWidth + symbolOffset, (int) pos.y + (img.getHeight() * scaleHUD) - 22 * scaleHUD);
        }
        if (inBuyingZone && Player.myPlayer.isInBuyingTime()) {
            pos.x = (10) * ratio;
            pos.y = (int) (squareRes) * (int) (cameraWidth / 3 - 1) / ratio;
            img = hudSymbols.get(4);
            pos.y += img.getHeight();
            g2D.drawImage(img, (int) pos.x, (int) pos.y, (int) (img.getWidth() * scaleHUD), (int) (img.getHeight() * scaleHUD));
            //g2D.setColor(Color.green);
            g2D.setFont(new javafx.scene.text.Font("TimesRoman", (int) (22 * scaleHUD)));
            g2D.setStroke(Color.rgb(255, 255, 255));
            g2D.fillText("BuyZone", (int) pos.x + hpSymbolWidth + symbolOffset, (int) pos.y + (img.getHeight() * scaleHUD) - 22 * scaleHUD);
        }
        if (storeError < 0) { //TODO: Display error msg during x time
            pos.x = screenWidth / 2.0 - timeTotalWidth / 2.0;
            pos.y = (int) (squareRes) * (int) (cameraWidth / 3 - 1) / ratio;
            //g2D.setColor(Color.red);
            //g2D.setFont(new Font("TimesRoman", Font.PLAIN, (int) (11 * ratio)));
            //g2D.drawString("Can't buy...", (int) pos.x, (int) pos.y);
            storeError = 0;
        }
        g2D.restore();
        g2D.save();

        g2D.setEffect(new DropShadow(5, 1, 1, Color.BLACK));
        g2D.setTextAlign(TextAlignment.CENTER);

        g2D.setFill(Color.RED);
        if (buyErrorAnim.getValue() > 0.0) {
            double opacity = Math.min(buyErrorAnim.getValue() * 2, 1.0);

            g2D.setFill(Color.rgb(255, 0, 0, opacity));
            g2D.fillText("Cannot buy that weapon!", screenWidth / 2, screenHeight / 2);
        } else if (shopErrorAnim.getValue() > 0.0) {
            double opacity = Math.min(shopErrorAnim.getValue() * 2, 1.0);

            g2D.setFill(Color.rgb(255, 0, 0, opacity));
            g2D.fillText("Cannot open the store now!", screenWidth / 2, screenHeight / 2);
        }

        g2D.restore();
    }

    protected void drawChat(GraphicsContext gd) {
        // SREEN PARAMETERS
        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();

        // UI PARAMETERS
        double scaleHUD = getHudScale();
        int screenBorder = (int) (16 * scaleHUD);
        Image zeroImg = hudNumbers.get(0);
        int digitWidth = (int) (zeroImg.getWidth() * scaleHUD);
        int digitHeight = (int) (zeroImg.getHeight() * scaleHUD);
        int symbolOffset = (int) (8 * scaleHUD); // espacio entre simbolo y digitos
        int digitOffset = (int) (2 * scaleHUD); // epsacio entre digitos

        // Get messages to show
        long messagesShowTime = 10000; //How long they last in the box
        List<ChatMessage> shownMessages = GamemodeManager.getInstance()
                .getChatMessagesAfter(System.currentTimeMillis() - messagesShowTime, Player.myPlayer);

        // Print chat box
        double messageHeight = 48 * scaleHUD;
        Point screenPos = new Point(screenBorder, screenHeight - screenBorder * 6 - digitHeight);
        int maxMessagesToShow = 8;

        // Set font
        javafx.scene.text.Font chatFont = new javafx.scene.text.Font("Arial", 32 * scaleHUD);
        double messageSpacing = 8 * scaleHUD;
        gd.setFont(chatFont);
        for (int i = 0; i < shownMessages.size() && i < maxMessagesToShow; i++) {
            ChatMessage msg = shownMessages.get(shownMessages.size() - 1 - i); //Get messages from later to earlier

            String senderText = msg.getSenderName();
            if (msg.isGlobal()) {
                senderText += "(Global): ";
            } else {
                senderText += "(Team): ";
            }
            String msgText = msg.getMessage();
            int newLines = StringUtils.countMatches(msgText, "\n");
            screenPos.y -= chatFont.getSize()*(1+newLines) + messageSpacing;

            // Paint shadow
            gd.setFill(javafx.scene.paint.Color.BLACK);
            gd.fillText(senderText + msgText, screenPos.getX() + 2, screenPos.getY() + 2);

            // Paint message
            gd.setFill(javafx.scene.paint.Color.YELLOW);
            gd.fillText(senderText + msgText, screenPos.getX(), screenPos.getY());

            // Paint sender
            gd.setFill(msg.getSenderColor());
            gd.fillText(senderText, screenPos.getX(), screenPos.getY());
        }

    }


    protected void drawKills(GraphicsContext gd) {
        // SREEN PARAMETERS
        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();

        // UI PARAMETERS
        double scaleHUD = getHudScale();
        int screenBorder = (int) (16 * scaleHUD);
        Image zeroImg = hudNumbers.get(0);
        int digitWidth = (int) (zeroImg.getWidth() * scaleHUD);
        int digitHeight = (int) (zeroImg.getHeight() * scaleHUD);
        int symbolOffset = (int) (8 * scaleHUD); // espacio entre simbolo y digitos
        int digitOffset = (int) (2 * scaleHUD); // epsacio entre digitos

        // Color Effect for weapon iamge
        ColorAdjust colorAdjust = new ColorAdjust();
        colorAdjust.setContrast(1.0);
        colorAdjust.setBrightness(0.4);
        colorAdjust.setSaturation(1.0);
        colorAdjust.setHue(0.25);

        // Get messages to show
        long killsShowTime = 7000; //How long they last in the box
        List<KillLog> shownLogs = GamemodeManager.getInstance()
                .getKillLogsAfter(System.currentTimeMillis() - killsShowTime);

        // Print kills
        double logsHeight = 32 * scaleHUD;
        double heightOffset = 0;
        if (Player.myPlayer == null || !Player.myPlayer.isAlive()) {
            heightOffset = 128 * scaleHUD;
        }
        Point screenPos = new Point(screenWidth - screenBorder, (int) (screenBorder * 2 + logsHeight + heightOffset));
        int maxMessagesToShow = 16;

        // Set font
        javafx.scene.text.Font chatFont = new javafx.scene.text.Font("Arial", logsHeight);
        gd.setTextAlign(TextAlignment.RIGHT);
        double messageSpacing = 8 * scaleHUD;
        gd.setFont(chatFont);
        for (int i = 0; i < shownLogs.size() && i < maxMessagesToShow; i++) {
            KillLog log = shownLogs.get(i); //Get messages from later to earlier

            Image wpnImage = log.getWeaponImage();
            double imageWidth = 0;
            double imageHeight = 0;
            if (wpnImage != null) {
                imageWidth = wpnImage.getWidth() * scaleHUD * 2;
                imageHeight = wpnImage.getHeight() * scaleHUD * 2;
            }

            String wpnText = log.getWeaponName();

            // Paint victim NAME
            screenPos.x = screenWidth - screenBorder;
            String victimtext = log.getVictimName();
            javafx.scene.paint.Color victimColor = log.getVictimColor();

            // Shadow
            gd.setFill(javafx.scene.paint.Color.BLACK);
            gd.fillText(victimtext, screenPos.getX() + 1, screenPos.getY() + 1);

            // Colored text
            gd.setFill(victimColor);
            gd.fillText(victimtext, screenPos.getX(), screenPos.getY());

            // Paint weapon
            gd.setEffect(colorAdjust);
            gd.setGlobalBlendMode(BlendMode.ADD);
            Text auxText = new Text(victimtext);
            auxText.setFont(gd.getFont());
            double victimTextWidth = auxText.getLayoutBounds().getWidth();
            screenPos.x -= victimTextWidth + imageWidth + symbolOffset;

            if (Configuration.isDeathNoticesImages() && wpnImage != null) {
                gd.drawImage(wpnImage, screenPos.getX(), screenPos.getY() - imageHeight, imageWidth, imageHeight);
                screenPos.x -= symbolOffset;
            } else {
                screenPos.x += imageWidth;

                gd.setFill(Color.WHITE);
                gd.fillText(log.getWeaponName(), screenPos.getX(), screenPos.getY());

                auxText = new Text(log.getWeaponName());
                auxText.setFont(gd.getFont());
                double weaponWidth = auxText.getLayoutBounds().getWidth();
                screenPos.x -= weaponWidth + symbolOffset;
            }

            gd.setEffect(null);
            gd.setGlobalBlendMode(BlendMode.SRC_OVER);

            // Paint killer NAME
            String killerText = log.getKillerName();
            javafx.scene.paint.Color killerColor = log.getKillerColor();

            // Shadow
            gd.setFill(javafx.scene.paint.Color.BLACK);
            gd.fillText(killerText, screenPos.getX() + 1, screenPos.getY() + 1);

            // Colored text
            gd.setFill(killerColor);
            gd.fillText(killerText, screenPos.getX(), screenPos.getY());

            screenPos.y += symbolOffset * 2 + logsHeight;
        }
        gd.setTextAlign(TextAlignment.LEFT);

    }

    private List<Integer> getNDigits(int number, int nDigits) {
        List<Integer> digits = new ArrayList<>();
        if (nDigits == -1) {
            do {
                digits.add(number % 10);
                number = number / 10;
            } while (number > 0);
        } else {
            for (int i = 0; i < nDigits; i++) {
                digits.add(number % 10);
                number = number / 10;
            }
        }
        return digits;
    }

    private void initHud() {
        try {
            BufferedImage bimg = ImageIO.read(getClass().getClassLoader().getResourceAsStream("Sprites/hud/hud_nums.bmp"));
            Image img = SwingFXUtils.toFXImage(Transparency.makeBackgroundTransparent(bimg), null);
            //img = GraphicsUtils.toCompatibleImage(img);
            this.hudNumbers = new ArrayList<>();
            int width = (int) img.getWidth() / 12 - 1;
            for (int i = 0; i < 12; i++) {
                hudNumbers.add(GraphicsUtils.getSubimage(img, i * width, 0, width, (int) img.getHeight()));
            }

            //this.hudNumbers = new SpriteSheet(tImg, 13, 1);
            bimg = ImageIO.read(getClass().getClassLoader().getResourceAsStream("Sprites/hud/hud_symbols.bmp"));
            bimg = Transparency.makeBackgroundTransparent(bimg);
            //img = GraphicsUtils.toCompatibleImage(img);
            //tImg = BMPDecoder.read(getClass().getClassLoader().getResourceAsStream("Sprites/hud/hud_symbols.bmp"));
            this.hudSymbols = new SpriteSheet(bimg, 13, 1);

            bimg = ImageIO.read(getClass().getClassLoader().getResourceAsStream("Sprites/hud/hud_radar_simple.png"));
            //bimg = Transparency.makeBackgroundTransparent(bimg);
            //img = GraphicsUtils.toCompatibleImage(img);
            this.radar = SwingFXUtils.toFXImage(bimg, null);

            bimg = ImageIO.read(getClass().getClassLoader().getResourceAsStream("Sprites/player/marker.bmp"));
            this.marker = SwingFXUtils.toFXImage(Transparency.makeBackgroundTransparent(bimg), null);

            bimg = ImageIO.read(getClass().getClassLoader().getResourceAsStream("Sprites/bomb_radar.png"));
            this.bombRadarImg = SwingFXUtils.toFXImage(bimg, null);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void initStore() {
        this.storeWeapons = new ArrayList<>(5);
        List<Weapon_info> weapons = Player.myPlayer.getTeam().getWeapons();
        for (int j = 0; j < 6; j++) {
            storeWeapons.add(new ArrayList<Weapon_info>());
        }
        for (Weapon_info w : weapons) {
            if (w.getType() >= 0 && w.getType() <= 4) {
                storeWeapons.get(w.getType()).add(w);
            }
            //Equipment
            else if (w.getType() == 6) {
                if (!w.getName().equals("defusekit") || (GamemodeManager.getInstance() instanceof StandardManager)) {
                    storeWeapons.get(w.getType() - 1).add(w);
                }
            }
        }
    }

    public void numberPress(int number) {
        if (renderPanel == -1) {
            if (number >= 1 && number <= 6) {
                renderPanel = number - 1;
            }
        } else {
            if (number <= storeWeapons.get(renderPanel).size()) {
                if (!Player.myPlayer.tryToBuy(storeWeapons.get(renderPanel).get(number - 1))) {
                    storeError = -1;
                }
                this.setStoreOpen(false);
            }
        }
    }

    public boolean isStoreOpen() {
        return storeOpen;
    }

    public boolean isEscMenuOpen() {
        return escMenuOpen;
    }

    public void setStoreOpen(boolean storeOpen) {
        shopOpenAnim.reset();
        this.storeOpen = storeOpen;
        renderPanel = -1;

        //Fix shot when closing storeb
        if (Player.myPlayer != null) {
            Player.myPlayer.timePrev = System.currentTimeMillis() + 1;
        }
    }

    public void setEscMenuOpen(boolean escOpen) {
        escMenuAnim.reset();
        this.escMenuOpen = escOpen;

        //Fix shot when closing menu
        if (Player.myPlayer != null) {
            Player.myPlayer.timePrev = System.currentTimeMillis() + 1;
        }
    }

    public void setBuyError() {
        this.buyErrorAnim.reset();
    }

    public void setShopError() {
        this.shopErrorAnim.reset();
    }

    private void drawWeaponPanel(GraphicsContext g2D, Point topLeft, Point mouseWindowPos) {
        int fontHeight = 13;
        double fontHeightMultiplier = 1.5, stringWidth;
        Color lightGray = Color.rgb(192, 192, 192);
        javafx.scene.text.Font f12 = new javafx.scene.text.Font("Arial", fontHeight);
        Color color = new Color(30 / 255.0, 30 / 255.0, 30 / 255.0, 200 / 255.0);
        Color white = new Color(1.0, 1.0, 1.0, 1.0);
        Text auxText = new Text();
        auxText.setFont(f12);

        topLeft.x += xOffset / 6.0;
        Point aux1 = new Point(topLeft.x, topLeft.y);
        topLeft.y += buttonHeight / 2.0 + 2 * yOffset;

        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        g2D.setFont(f12);
        g2D.fillText("Buy - " + classes[renderPanel], (int) topLeft.x, (int) topLeft.y);
        topLeft.y += 2 * yOffset;
        g2D.strokeLine((int) topLeft.x, (int) topLeft.y, (int) (topLeft.x + storeWidth - 2 * xOffset / 6.0), (int) topLeft.y);
        topLeft.y += 2 * yOffset;
        Point aux2 = new Point(topLeft.x, topLeft.y);
        for (int buyNum = 1; buyNum < storeWeapons.get(renderPanel).size() + 1; buyNum++) {
            drawButtonWithImage(g2D, topLeft, white, color, lightGray, fontHeightMultiplier, buyNum, storeWeapons.get(renderPanel).get(buyNum - 1), null, mouseWindowPos);
            if (buyNum == 1) {
                drawMoney(g2D, aux2, white, color, fontHeightMultiplier);
            }
        }
        /*Draw close button*/
        drawCloseButton(g2D, aux1, white, color, lightGray, fontHeightMultiplier, mouseWindowPos);
        drawBackButton(g2D, aux1, white, color, lightGray, fontHeightMultiplier, mouseWindowPos);
    }


    private void drawEquipmentPanel(GraphicsContext g2D, Point topLeft, Point mouseWindowPos) {
        int fontHeight = 13;
        double fontHeightMultiplier = 1.5, stringWidth;
        Color lightGray = Color.rgb(192, 192, 192);
        javafx.scene.text.Font f12 = new javafx.scene.text.Font("Arial", fontHeight);
        Color color = new Color(30 / 255.0, 30 / 255.0, 30 / 255.0, 200 / 255.0);
        Color white = new Color(1.0, 1.0, 1.0, 1.0);
        Text auxText = new Text();
        auxText.setFont(f12);

        topLeft.x += xOffset / 6.0;
        Point aux1 = new Point(topLeft.x, topLeft.y);
        topLeft.y += buttonHeight / 2.0 + 2 * yOffset;

        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        g2D.setFont(f12);
        g2D.fillText("Buy - Equipment", (int) topLeft.x, (int) topLeft.y);
        topLeft.y += 2 * yOffset;
        g2D.strokeLine((int) topLeft.x, (int) topLeft.y, (int) (topLeft.x + storeWidth - 2 * xOffset / 6.0), (int) topLeft.y);
        topLeft.y += 2 * yOffset;
        Point aux2 = new Point(topLeft.x, topLeft.y);
        drawButton(g2D, topLeft, white, color, lightGray, fontHeightMultiplier, 1, mouseWindowPos, "Kevlar");
        drawMoney(g2D, aux2, white, color, fontHeightMultiplier);
        drawButton(g2D, topLeft, white, color, lightGray, fontHeightMultiplier, 2, mouseWindowPos, "Kevlar+Helm");
        /*Draw close button*/
        drawCloseButton(g2D, aux1, white, color, lightGray, fontHeightMultiplier, mouseWindowPos);
        drawBackButton(g2D, aux1, white, color, lightGray, fontHeightMultiplier, mouseWindowPos);
    }

    private void drawMoney(GraphicsContext g2D, Point topLeft, Color white, Color color, double fontHeightMultiplier) {
        int tempX = (int) (topLeft.x + storeWidth - 2 * xOffset / 6.0 - buttonWidth / 3);
        g2D.setFill(color);
        g2D.fillRoundRect(tempX, (int) topLeft.y, buttonWidth / 3.0, buttonHeight, arc, arc);
        g2D.setStroke(white);
        g2D.setFill(white);
        g2D.strokeRoundRect(tempX, (int) topLeft.y, buttonWidth / 3.0, buttonHeight, arc, arc);
        Text auxText = new Text(Player.myPlayer.getMoney() + " $");
        auxText.setFont(f12);
        double stringWidth = auxText.getLayoutBounds().getWidth();
        tempX += (buttonWidth / 3 - stringWidth) / 2;
        int tempY = (int) (topLeft.y + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.fillText(Player.myPlayer.getMoney() + " $", tempX, tempY);
    }

    private void drawWeaponInfo(GraphicsContext g2D, Color white, Color color, Color lightGray, double fontHeightMultiplier, int buyNum, Weapon_info w, Point mouseWindowPos) {
        Point aux = new Point(storeReference.x, storeReference.y);
        aux.x += buttonWidth + xOffset / 2;
        aux.y += storeHeight / 2;
        g2D.setFill(color);
        g2D.fillRoundRect(aux.x, aux.y, storeWidth / 2.0, buttonHeight * 8, arc, arc);
        g2D.setStroke(white);
        g2D.strokeRoundRect(aux.x, aux.y, storeWidth / 2.0, buttonHeight * 8, arc, arc);
        double iWidth = w.getShopImage2().getWidth() * 4 * getHudScale(), iHeight = w.getShopImage2().getHeight() * 4 * getHudScale();

        double yPos = (storeReference.y + buttonHeight / 2.0 + 4 * yOffset);
        yPos = yPos + (aux.y - yPos - iHeight) / 2;
        g2D.drawImage(w.getShopImage2(), aux.x + (storeWidth / 2.0 - iWidth) / 2.0, yPos, iWidth, iHeight);
        String[] fieldNames;
        String[] fieldValues;
        if (w.getType() != 6) {
            fieldNames = new String[]{"Name", "Price", "Damage", "Ammo", "Rate of Fire", "Range", "Weight", "Accuracy"};
            fieldValues = new String[]{w.getDisplayName(), w.getPrice() + " $", String.valueOf(w.getDamage()), w.getAmmo_charger() + "|" + w.getAmmo_total(), String.valueOf(w.getReloadTime()), String.valueOf(w.getRange()), String.valueOf(w.getWeight()), String.valueOf(w.getRecoil_accuracy())};
        } else {
            if(!w.getName().equals("defusekit")){
                fieldNames = new String[]{"Name", "Price", "Armor"};
                fieldValues = new String[]{w.getDisplayName(), w.getPrice() + " $", String.valueOf(w.getDamage())};
            }
            else {
                fieldNames = new String[]{"Name", "Price"};
                fieldValues = new String[]{w.getDisplayName(), w.getPrice() + " $"};
            }

        }
        g2D.setStroke(lightGray);
        g2D.setFill(lightGray);
        Text auxText = new Text();
        auxText.setFont(f12);
        aux.x += (storeWidth / 2.0) / 80;
        aux.y += 3 * fontHeight / 2;
        for (int i = 0; i < fieldNames.length; i++) {
            g2D.fillText(fieldNames[i] + ":", aux.x, aux.y);
            auxText.setText(fieldValues[i]);
            g2D.fillText(fieldValues[i], aux.x + storeWidth / 2.0 - (storeWidth / 2.0) / 40 - auxText.getLayoutBounds().getWidth(), aux.y);
            aux.y += 3 * fontHeight / 2;
        }
    }

    private void drawButton(GraphicsContext g2D, Point topLeft, Color white, Color color, Color lightGray, double fontHeightMultiplier, int buyNum, Point mouseWindowPos, String text) {
        if (new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight).contains(mouseWindowPos.x, mouseWindowPos.y)) {
            g2D.setFill(this.buttonGradient);
        } else g2D.setFill(color);
        g2D.fillRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        buttons.add(new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight));
        g2D.setStroke(white);
        g2D.strokeRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        topLeft.x += (int) (buttonWidth / 60.0);
        int tempY = (int) (topLeft.y + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.fillText(String.valueOf(buyNum), (int) topLeft.x, tempY);
        Text auxText = new Text(String.valueOf(buyNum));
        auxText.setFont(f12);
        double stringWidth = auxText.getLayoutBounds().getWidth();
        //tempX = (int) (topLeft.x + 13 * (String.valueOf(buyNum)).length());
        tempY = (int) (topLeft.y + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.setFill(white);
        g2D.setStroke(white);
        g2D.fillText(text, topLeft.x, tempY);
        topLeft.x -= (int) (buttonWidth / 60.0);
        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        topLeft.y += buttonHeight + yOffset;

    }

    private void drawButtonWithImage(GraphicsContext g2D, Point topLeft, Color white, Color color, Color lightGray, double fontHeightMultiplier, int buyNum, Weapon_info w, Integer wClass, Point mouseWindowPos) {
        if (new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight).contains(mouseWindowPos.x, mouseWindowPos.y)) {
            if (wClass == null) {
                drawWeaponInfo(g2D, white, color, lightGray, fontHeightMultiplier, buyNum, storeWeapons.get(renderPanel).get(buyNum - 1), mouseWindowPos);
            }
            g2D.setFill(this.buttonGradient);
        } else g2D.setFill(color);
        g2D.fillRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        buttons.add(new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight));
        g2D.setStroke(white);
        g2D.strokeRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        topLeft.x += (int) (buttonWidth / 60.0);
        int tempY = (int) (topLeft.y + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.fillText(String.valueOf(buyNum), (int) topLeft.x, tempY);
        Image wImage = w.getShopImage();
        double iWidth = wImage.getWidth();
        double iHeight = wImage.getHeight();
        Text auxText = new Text(String.valueOf(buyNum));
        auxText.setFont(f12);
        double stringWidth = auxText.getLayoutBounds().getWidth();
        if (iWidth > buttonWidth / 7.5) {
            //scale width to fit
            iWidth = (buttonWidth / 7.5);
            //scale height to maintain aspect ratio
            iHeight = (iWidth * iHeight) / wImage.getWidth();
        }
        //tempX = (int) (topLeft.x + 13 * (String.valueOf(buyNum)).length());
        int tempX = (int) (topLeft.x + stringWidth + ((buttonWidth / 4 - stringWidth) - iWidth) / 2); //TODO: Esta regular
        tempY = (int) (topLeft.y + (buttonHeight - iHeight) / 2);
        g2D.drawImage(wImage, tempX, tempY, iWidth, iHeight);
        tempX = (int) (topLeft.x + buttonWidth / 4);
        tempY = (int) (topLeft.y + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.setFill(white);
        g2D.setStroke(white);
        if (wClass != null) {
            g2D.fillText(classes[wClass], tempX, tempY);
            for (Weapon_info wi : this.storeWeapons.get(wClass)) {

            }
        } else g2D.fillText(w.getDisplayName(), tempX, tempY);
        topLeft.x -= (int) (buttonWidth / 60.0);
        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        if (wClass == null) {
            auxText.setText(w.getPrice() + " $");
            tempX = (int) (topLeft.x + buttonWidth - 2 * buttonWidth / 60.0 - auxText.getLayoutBounds().getWidth());
            g2D.fillText(w.getPrice() + " $", tempX, tempY);
        }
        topLeft.y += buttonHeight + yOffset;

    }

    private void drawBackButton(GraphicsContext g2D, Point topLeft, Color white, Color color, Color lightGray, double fontHeightMultiplier, Point mouseWindowPos) {
        topLeft.y -= (buttonHeight + yOffset);
        if (new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight).contains(mouseWindowPos.x, mouseWindowPos.y)) {
            g2D.setFill(this.buttonGradient);
        } else g2D.setFill(color);
        g2D.fillRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        buttons.add(new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight));
        g2D.setFill(white);
        g2D.setStroke(white);
        g2D.strokeRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        g2D.setFill(lightGray);
        int tempX = (int) (topLeft.x + buttonWidth / 60.0);
        int tempY = (int) (topLeft.y + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.setFill(white);
        g2D.setStroke(white);
        g2D.fillText("Back", tempX, tempY);
    }

    private void drawCloseButton(GraphicsContext g2D, Point topLeft, Color white, Color color, Color lightGray, double fontHeightMultiplier, Point mouseWindowPos) {
        topLeft.y += storeHeight - 2 * buttonHeight;
        if (new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight).contains(mouseWindowPos.x, mouseWindowPos.y)) {
            g2D.setFill(this.buttonGradient);
        } else g2D.setFill(color);
        g2D.fillRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        buttons.add(new Rectangle2D.Double(topLeft.x, topLeft.y, buttonWidth, buttonHeight));
        g2D.setFill(white);
        g2D.setStroke(white);
        g2D.strokeRoundRect((int) topLeft.x, (int) topLeft.y, buttonWidth, buttonHeight, arc, arc);
        g2D.setFill(lightGray);
        int tempX = (int) (topLeft.x + buttonWidth / 60.0);
        int tempY = (int) (topLeft.y + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.setFill(white);
        g2D.setStroke(white);
        g2D.fillText(0 + " Close", (int) tempX, tempY);
    }

    private void drawEquipmentButton(GraphicsContext g2D, Point topLeft, Color white, Color color, Color lightGray, int buyNum, double fontHeightMultiplier, Point mouseWindowPos) {
        int tempY = topLeft.y + buttonHeight;
        if (new Rectangle2D.Double(topLeft.x, tempY, buttonWidth, buttonHeight).contains(mouseWindowPos.x, mouseWindowPos.y)) {
            g2D.setFill(this.buttonGradient);
        } else g2D.setFill(color);
        g2D.fillRoundRect((int) topLeft.x, tempY, buttonWidth, buttonHeight, arc, arc);
        buttons.add(new Rectangle2D.Double(topLeft.x, tempY, buttonWidth, buttonHeight));
        g2D.setStroke(white);
        g2D.strokeRoundRect((int) topLeft.x, tempY, buttonWidth, buttonHeight, arc, arc);
        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        topLeft.x += (int) (buttonWidth / 60.0);
        tempY = (int) (tempY + (buttonHeight - fontHeight) * fontHeightMultiplier);
        g2D.fillText(buyNum + " Equipment", (int) topLeft.x, tempY);
    }

    private void drawMainStoreMenu(GraphicsContext g2D, Point topLeft, Point mouseWindowPos) {
        double fontHeightMultiplier = 1.5, stringWidth;
        Color lightGray = Color.rgb(192, 192, 192);
        Color color = new Color(30 / 255.0, 30 / 255.0, 30 / 255.0, 200 / 255.0);
        Color white = new Color(1.0, 1.0, 1.0, 1.0);
        Text auxText = new Text();
        auxText.setFont(f12);

        topLeft.x += xOffset / 6.0;
        Point aux1 = new Point(topLeft.x, topLeft.y);
        topLeft.y += buttonHeight / 2.0 + 2 * yOffset;

        g2D.setFill(lightGray);
        g2D.setStroke(lightGray);
        g2D.setFont(f12);
        g2D.fillText("Buy", (int) topLeft.x, (int) topLeft.y);
        topLeft.y += 2 * yOffset;
        g2D.strokeLine((int) topLeft.x, (int) topLeft.y, (int) (topLeft.x + storeWidth - 2 * xOffset / 6.0), (int) topLeft.y);
        topLeft.y += 2 * yOffset;
        Point aux2 = new Point(topLeft.x, topLeft.y);
        for (int buyNum = 1; buyNum < classes.length + 1; buyNum++) {
            drawButtonWithImage(g2D, topLeft, white, color, lightGray, fontHeightMultiplier, buyNum, storeWeapons.get(buyNum - 1).get(0), buyNum - 1, mouseWindowPos);
            if (buyNum == 1) {
                drawMoney(g2D, aux2, white, color, fontHeightMultiplier);
            }
        }
        //drawEquipmentButton(g2D, topLeft, white, color, lightGray, classes.length + 1, fontHeightMultiplier, mouseWindowPos);
        /*Draw close button*/
        drawCloseButton(g2D, aux1, white, color, lightGray, fontHeightMultiplier, mouseWindowPos);
    }

    private void drawStore(GraphicsContext g2D) {
        Point mouseScreenPos = MouseInfo.getPointerInfo().getLocation();
        Point windowPos = Helper.locationOnScreen();
        Point mouseWindowPos = new Point(mouseScreenPos.x - windowPos.x, mouseScreenPos.y - windowPos.y);


        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();

        Point pos = new Point((int) ((screenWidth - storeWidth) / 2.0), (int) ((screenHeight - storeHeight) / 2.0));
        //g2D.setColor(new Color(20, 20, 20, 200));
        g2D.setFill(new Color(20 / 255.0, 20 / 255.0, 20 / 255.0, 200 / 255.0));
        g2D.fillRoundRect((int) pos.x, (int) pos.y, storeWidth, storeHeight, 10, 10);
        buttons.clear();
        this.storeReference = new Point(pos.x, pos.y);
        if (this.renderPanel == -1) {
            drawMainStoreMenu(g2D, pos, mouseWindowPos);
        } else if (renderPanel >= 0 && renderPanel <= 5) {
            drawWeaponPanel(g2D, pos, mouseWindowPos);
        }

        double opacity = 1.0 - shopOpenAnim.getValue();
        g2D.setFill(Color.rgb(255, 255, 255, opacity));

        double animOffset = shopOpenAnim.getValue() * 16;
        pos = new Point((int) ((screenWidth - storeWidth) / 2.0), (int) ((screenHeight - storeHeight) / 2.0));
        g2D.fillRoundRect((int) pos.x - animOffset, (int) pos.y - animOffset, storeWidth + animOffset * 2, storeHeight + animOffset * 2, 10, 10);
    }

    protected List<MenuButton> getEscButtons() {
        double scaleHUD = getHudScale();
        int screenBorder = (int) (32 * scaleHUD);
        int symbolOffset = (int) (32 * scaleHUD); // espacio entre simbolo y digitos
        int digitOffset = (int) (2 * scaleHUD); // epsacio entre digitosint screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();

        Point screenPos = new Point(screenBorder, screenHeight / 2);

        double btnHeight = 32 * scaleHUD;
        List<MenuButton> escButtons = new ArrayList<>();
        escButtons.add(new MenuButton(screenPos.x, screenPos.y, Color.LIGHTGREY, Color.WHITE,
                "Resume game", "resume"));

        escButtons.add(new MenuButton(screenPos.x, screenPos.y + btnHeight + symbolOffset, Color.LIGHTGREY, Color.WHITE,
                "Options", "options"));

        escButtons.add(new MenuButton(screenPos.x, screenHeight - (btnHeight * 3 + screenBorder * 3), Color.LIGHTGREY, Color.WHITE,
                "Disconnect", "disconnect"));

        escButtons.add(new MenuButton(screenPos.x, screenHeight - (btnHeight * 2 + screenBorder * 2), Color.LIGHTGREY, Color.WHITE,
                "Quit", "quit"));

        return escButtons;
    }

    private void drawEscMenu(GraphicsContext gc) {
        int screenWidth = Helper.screenWidth();
        int screenHeight = Helper.screenHeight();
        double scaleHUD = getHudScale();
        int screenBorder = (int) (16 * scaleHUD);
        int symbolOffset = (int) (8 * scaleHUD); // espacio entre simbolo y digitos
        int digitOffset = (int) (2 * scaleHUD); // epsacio entre digitos
        gc.setFont(new javafx.scene.text.Font("Arial", (int) (28 * scaleHUD)));

        // Draw esc menu background
        double opacity = 0.5 * escMenuAnim.getValue();
        gc.setFill(Color.rgb(0, 0, 0, opacity));
        gc.setGlobalBlendMode(BlendMode.SRC_OVER);
        gc.fillRect(0, 0, screenWidth, screenHeight);

        // Draw buttons

        gc.setEffect(new DropShadow(2, 2, 5, Color.BLACK));
        List<MenuButton> escButtons = getEscButtons();
        for (int i = 0; i < escButtons.size(); i++) {
            escButtons.get(i).draw(gc);
        }
        gc.setEffect(null);
    }

    private void updateEscMenu() {
        List<MenuButton> escButtons = getEscButtons();

        String cmdString = "";
        for (int i = 0; i < escButtons.size(); i++) {
            if (escButtons.get(i).isClicked()) {

                play3DSound(escMenuSound, this.getPosition());

                cmdString = escButtons.get(i).getClickString();
                break;
            }
        }

        if (cmdString == "resume") {
            if(ConfigurationMenu.isVisible()) ConfigurationMenu.destroyMenu();
            setEscMenuOpen(false);
        } else if (cmdString == "disconnect") {
            Scene.getInstance().destroy();
            return;
        } else if (cmdString == "options") {

            new ConfigurationMenu();
        } else if (cmdString == "quit") {
            System.exit(0);
            return;
        }
    }

    public void notifyClick(double x, double y) {
        for (int i = 0; i < buttons.size(); i++) {
            if (buttons.get(i).contains(x, y)) {
                if (renderPanel == -1 && i < classes.length) renderPanel = i; //Click class button
                else if (renderPanel != -1 && i < storeWeapons.get(renderPanel).size()) { //Click to buy weapon
                    if (!Player.myPlayer.tryToBuy(storeWeapons.get(renderPanel).get(i))) {
                        storeError = -1;
                    }
                    this.setStoreOpen(false);
                } else if (renderPanel != -1 && i == storeWeapons.get(renderPanel).size() + 1)
                    renderPanel = -1;//Click back button
                else this.setStoreOpen(false); //Click close button
                i = buttons.size();
            }
        }
    }

    /**
     * Aux method to get accurate color in ColorAdjust
     */
    public static double map(double value, double start, double stop, double targetStart, double targetStop) {
        return targetStart + (targetStop - targetStart) * ((value - start) / (stop - start));
    }
}
